﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;
using YJKArchMethodLibrary.Utils;
using YJKCodeBase.WinForm;
using YJKView;
using Transfer.CommonUnit;

namespace ColumnModuleAndEdit.ColumnModule
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	internal class CmdColumnBreakBeam : IExternalCommand
	{
		public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			CmdViewType types = (CmdViewType)127;
			if (SwitchView.SetUsableView(types, cmdData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			this.m_cmdData = cmdData;
			this.m_doc = cmdData.Application.ActiveUIDocument.Document;
			this.m_selection = cmdData.Application.ActiveUIDocument.Selection;
			RevitVersionFuncs.ClearSelection(this.m_selection);
			Transaction transaction = new Transaction(this.m_doc, "ColumnBreakBeam");
			Result result;
			for (;;)
			{
				transaction.Start();
				ColumnFilter columnFilter = new ColumnFilter();
				IList<Element> list = null;
				try
				{
					list = this.m_selection.PickElementsByRectangle(columnFilter, "请框选柱子(仅支持混凝土结构柱打断混凝土梁)");
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					transaction.RollBack();
					result = Autodesk.Revit.UI.Result.Succeeded;
					break;
				}
				catch (Exception)
				{
					transaction.RollBack();
					result = Autodesk.Revit.UI.Result.Failed;
					break;
				}
				try
				{
					foreach (Element element in list)
					{
						int integerValue = element.Category.Id.IntegerValue;
						if (-2001330 == integerValue)
						{
							this.ColumnBreakBeam(element);
						}
					}
				}
				catch (Exception)
				{
					transaction.RollBack();
					result = Autodesk.Revit.UI.Result.Failed;
					break;
				}
				transaction.Commit();
			}
			return result;
		}

		private void ColumnBreakBeam(Element column)
		{
			List<FamilyInstance> beamsJoinedElement = this.GetBeamsJoinedElement(column);
			List<FamilyInstance> beamsIntersectElement = this.GetBeamsIntersectElement(column);
			beamsJoinedElement.AddRange(beamsIntersectElement);
			List<XYZ> list = new List<XYZ>();
			ColumnProfileExtractor columnProfileExtractor = new ColumnProfileExtractor(this.m_cmdData.Application);
			FamilyInstance column2 = column as FamilyInstance;
			List<EdgeInfo> columnProfile = columnProfileExtractor.GetColumnProfile(column2);
			foreach (EdgeInfo edgeInfo in columnProfile)
			{
				Curve curve = edgeInfo.ConvertTo(this.m_cmdData.Application.Application);
				list.AddRange(curve.Tessellate());
			}
			AssistFunc.CompressArray(list);
			foreach (FamilyInstance familyInstance in beamsJoinedElement)
			{
				LocationCurve locationCurve = familyInstance.Location as LocationCurve;
				Curve curve2 = locationCurve.Curve;
				XYZ endPoint = curve2.GetEndPoint(0);
				XYZ endPoint2 = curve2.GetEndPoint(1);
				if (Geometry.PointInPloygon(list, endPoint, 0.0001, 0.0001) == -1 && Geometry.PointInPloygon(list, endPoint2, 0.0001, 0.0001) == -1)
				{
					this.ColumnBreakBeam(column, familyInstance);
				}
			}
		}

		private void ColumnBreakBeam(Element column, FamilyInstance beam)
		{
			LocationCurve locationCurve = beam.Location as LocationCurve;
			Curve curve = locationCurve.Curve;
			XYZ endPoint = curve.GetEndPoint(0);
			XYZ endPoint2 = curve.GetEndPoint(1);
			LocationPoint locationPoint = column.Location as LocationPoint;
			XYZ point = locationPoint.Point;
			XYZ breakPoint = this.GetBreakPoint(point, beam);
			int elementCount = MirrorOperater.GetElementCount(this.m_doc);
			XYZ xyz = new XYZ(0.0, 12345.0, 0.0);
			ICollection<ElementId> source = ElementTransformUtils.CopyElement(this.m_doc, beam.Id, xyz);
			ICollection<ElementId> source2 = ElementTransformUtils.CopyElement(this.m_doc, beam.Id, xyz);
			FamilyInstance familyInstance = this.m_doc.GetElement(source.ElementAt(0)) as FamilyInstance;
			FamilyInstance familyInstance2 = this.m_doc.GetElement(source2.ElementAt(0)) as FamilyInstance;
			LocationCurve locationCurve2 = familyInstance.Location as LocationCurve;
			LocationCurve locationCurve3 = familyInstance2.Location as LocationCurve;
			List<ElementId> elementsIdAfter = MirrorOperater.GetElementsIdAfter(elementCount, this.m_doc);
			this.m_doc.Delete(beam.Id);
			this.RemoveElementsExceedBeam(endPoint + xyz, breakPoint + xyz, familyInstance, elementsIdAfter);
			this.RemoveElementsExceedBeam(breakPoint + xyz, endPoint2 + xyz, familyInstance2, elementsIdAfter);
			Line line = locationCurve2.Curve as Line;
			if (null != line)
			{
				locationCurve2.Curve = Line.CreateBound(endPoint + xyz, breakPoint + xyz);
				locationCurve3.Curve = Line.CreateBound(breakPoint + xyz, endPoint2 + xyz);
			}
			Arc arc = locationCurve2.Curve as Arc;
			if (null != arc)
			{
				XYZ xyz2 = AxisAssistFunc.CalculatMidPoint(endPoint + xyz, breakPoint + xyz, arc.Center + xyz, arc.Normal);
				locationCurve2.Curve = Arc.Create(endPoint + xyz, breakPoint + xyz, xyz2);
				xyz2 = AxisAssistFunc.CalculatMidPoint(breakPoint + xyz, endPoint2 + xyz, arc.Center + xyz, arc.Normal);
				locationCurve3.Curve = Arc.Create(breakPoint + xyz, endPoint2 + xyz, xyz2);
			}
			ElementTransformUtils.MoveElement(this.m_doc, familyInstance.Id, xyz.Negate());
			ElementTransformUtils.MoveElement(this.m_doc, familyInstance2.Id, xyz.Negate());
			this.m_doc.Regenerate();
		}

		private List<FamilyInstance> GetBeamsJoinedElement(Element column)
		{
			List<FamilyInstance> list = new List<FamilyInstance>();
			ICollection<ElementId> joinedElements = JoinGeometryUtils.GetJoinedElements(this.m_doc, column);
			foreach (ElementId elementId in joinedElements)
			{
				Element element = this.m_doc.GetElement(elementId);
				int integerValue = element.Category.Id.IntegerValue;
				if (-2001320 == integerValue)
				{
					list.Add(element as FamilyInstance);
				}
			}
			return list;
		}

		private List<FamilyInstance> GetBeamsIntersectElement(Element column)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.OfClass(typeof(FamilyInstance));
			ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(column);
			filteredElementCollector.WherePasses(elementIntersectsElementFilter);
			List<FamilyInstance> list = new List<FamilyInstance>();
			foreach (Element element in filteredElementCollector)
			{
				int integerValue = element.Category.Id.IntegerValue;
				if (-2001320 == integerValue)
				{
					list.Add(element as FamilyInstance);
				}
			}
			return list;
		}

		private List<Element> GetAssociateElementByBeam(FamilyInstance beam, List<Element> elements)
		{
			List<Element> list = new List<Element>();
			foreach (Element element in elements)
			{
				Opening opening = element as Opening;
				if (opening != null && opening.Host != null && opening.Host.Id == beam.Id)
				{
					list.Add(opening);
				}
			}
			return list;
		}

		private void RemoveElementsExceedBeam(XYZ ptStart, XYZ ptEnd, FamilyInstance beam, List<ElementId> eleIds)
		{
			List<Element> list = new List<Element>();
			foreach (ElementId elementId in eleIds)
			{
				Element element = this.m_doc.GetElement(elementId);
				list.Add(element);
			}
			List<Element> associateElementByBeam = this.GetAssociateElementByBeam(beam, list);
			LocationCurve locationCurve = beam.Location as LocationCurve;
			Curve curve = locationCurve.Curve;
			Curve curve2 = null;
			Line line = curve as Line;
			if (null != line)
			{
				curve2 = Line.CreateBound(ptStart, ptEnd);
			}
			Arc arc = curve as Arc;
			if (null != arc)
			{
				XYZ xyz = AxisAssistFunc.CalculatMidPoint(ptStart, ptEnd, arc.Center, arc.Normal);
				curve2 = Arc.Create(ptStart, ptEnd, xyz);
			}
			foreach (Element element2 in associateElementByBeam)
			{
				Opening opening = element2 as Opening;
				if (opening != null)
				{
					XYZ pointOnOpenging = this.GetPointOnOpenging(opening);
					ConnectHelper connectHelper = new ConnectHelper();
					if (connectHelper.Project(pointOnOpenging, curve2, 0.0001) == null)
					{
						this.m_doc.Delete(opening.Id);
					}
				}
			}
		}

		private XYZ GetPointOnOpenging(Opening opening)
		{
			XYZ result = XYZ.Zero;
			if (opening.IsRectBoundary)
			{
				IList<XYZ> boundaryRect = opening.BoundaryRect;
				XYZ xyz = boundaryRect[1] - boundaryRect[0];
				result = boundaryRect[0] + xyz / 2.0;
			}
			else
			{
				CurveArray boundaryCurves = opening.BoundaryCurves;
                Curve curve = boundaryCurves.get_Item(0);
				Line line = curve as Line;
				if (null != line)
				{
					result = line.GetEndPoint(0);
				}
				NurbSpline nurbSpline = curve as NurbSpline;
				if (null != nurbSpline)
				{
					result = nurbSpline.GetEndPoint(0);
				}
				Arc arc = curve as Arc;
				if (null != arc)
				{
					result = arc.Center;
				}
				Ellipse ellipse = curve as Ellipse;
				if (null != ellipse)
				{
					result = ellipse.Center;
				}
			}
			return result;
		}

		private XYZ GetBreakPoint(XYZ ptColumn, Element beam)
		{
			LocationCurve locationCurve = beam.Location as LocationCurve;
			Curve curve = locationCurve.Curve;
			return curve.Project(ptColumn).XYZPoint;
		}

		private ExternalCommandData m_cmdData;

		private Document m_doc;

		private Selection m_selection;

		public static WindowHandle _hWndRevit;
	}
}
